#!/usr/bin/env python3
# -*- coding: utf-8 -*-
#
# Copyright (c) 2020, Erik Henriksson
# Copyright (c) 2021-2023, Christopher Durand
# Copyright (c) 2021, Niklas Hauser
#
# This file is part of the modm project.
#
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
# -----------------------------------------------------------------------------

def init(module):
    module.name = ":processing:fiber"
    module.description = FileReader("module.md")

def prepare(module, options):
    module.depends(":architecture:clock", ":architecture:atomic",
                   ":architecture:assert", ":architecture:fiber", ":stdc++")

    core = options[":target"].get_driver("core")["type"]
    if core.startswith("cortex-m"): module.depends(":cmsis:device")
    return (core.startswith("cortex-m") or core.startswith("avr") or
            "x86_64" in core or "arm64" in core)


def build(env):
    env.outbasepath = "modm/src/modm/processing/fiber"
    env.substitutions = {
        "with_task": True,
    }
    env.template("../fiber.hpp.in")

    core = env[":target"].get_driver("core")["type"]
    with_fpu = env.get(":platform:cortex-m:float-abi", "soft") != "soft"
    env.substitutions = {
        "is_cm0": core.startswith("cortex-m0"),
        "is_avr": core.startswith("avr"),
        "is_windows": env[":target"].identifier.family == "windows",
        "is_darwin": env[":target"].identifier.family == "darwin",
        "with_psplim": core.startswith("cortex-m") and sum(c.isnumeric() for c in core) == 2,
        "core": core,
        "with_fpu": with_fpu,
        "target": env[":target"].identifier,
        "multicore": env.has_module(":platform:multicore"),
        "num_cores": 1,
    }
    if env.has_module(":platform:multicore"):
        cores = int(env[":target"].identifier.cores)
        env.substitutions["num_cores"] = cores

    if core.startswith("cortex-m"):
        env.substitutions["stack_minimum"] = (2 + 9 + (16 if with_fpu else 0)) * 4
        env.substitutions["default_stack_size"] = 1024
        env.template("context_arm_m.cpp.in")

    elif core.startswith("avr"):
        env.substitutions["stack_minimum"] = 4 + 18 + 6 # -2 if PC only 2B
        env.substitutions["default_stack_size"] = 512
        env.copy("context_avr.cpp")

    elif "x86_64" in core:
        env.substitutions["stack_minimum"] = (30 + 2) * 8
        env.substitutions["default_stack_size"] = 2**20 # 1MB
        env.template("context_x86_64.cpp.in")

    elif "arm64" in core:
        env.substitutions["stack_minimum"] = (20 + 2) * 8
        env.substitutions["default_stack_size"] = 2**20 # 1MB
        env.copy("context_arm64.cpp")

    env.copy("context.h")
    env.template("stack.hpp.in")
    env.template("scheduler.hpp.in")
    env.copy("scheduler.cpp")
    env.copy("task.hpp")
    env.copy("task_impl.hpp")

    env.copy("mutex.hpp")
    env.copy("shared_mutex.hpp")
    env.copy("semaphore.hpp")
    env.copy("latch.hpp")
    env.copy("barrier.hpp")
    env.copy("stop_token.hpp")
    env.copy("condition_variable.hpp")
